<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <title>代码贡献规范 - 为企业级框架和应用而生</title>
  <meta charset="utf-8">
  <meta name="description" content="index.description">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <link rel="icon" href="/images/favicon.png" type="image/x-icon">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css" />
<link rel="stylesheet" href="/css/index.css">

    <script>
    !function(t,e,a,r,c){t.TracertCmdCache=t.TracertCmdCache||[],t[c]=window[c]||
      {_isInit:!0,call:function(){t.TracertCmdCache.push(arguments)},
      start:function(t){this.call('start',t)}},t[c].l=new Date;
      var n=e.createElement(a),s=e.getElementsByTagName(a)[0];
      n.async=!0,n.src=r,s.parentNode.insertBefore(n,s)}
    (window,document,'script','https://tracert.alipay.com/tracert.js','Tracert');
      Tracert.start({
        plugins: [ 'BucName' ],
        spmAPos: 'a454',
        spmBPos: 'b4893',
      });
    </script>
  
</head>
<body>
  <div class="nav" >
  <header>
    <a href="/zh-cn/" class="nav-logo leftpadding" alt="egg"><img src="https://zos.alipayobjects.com/rmsportal/VTcUYAaoKqXyHJbLAPyF.svg"></a>
    <ul class="nav-item">
      <li>
        <form id="search-form">
          <input type="text" id="search-query" class="search-query st-default-search-input">
        </form>
      </li>
      <li><a href="/zh-cn/intro/" alt="指南">指南</a></li><li><a href="/api/" alt="API">API</a></li><li><a href="/zh-cn/tutorials/index.html" alt="教程">教程</a></li><li><a href="https://github.com/search?q=topic%3Aegg-plugin&type=Repositories" alt="插件">插件</a></li><li><a href="https://github.com/eggjs/egg/releases" alt="发布日志">发布日志</a></li>
      
      
        <li class="translations">
          <a class="nav-link">Translations</a>
          <span class="arrow"></span><ul id="dropdownContent" class="dropdown-content"><li><a id="en" href="/en/contributing.html" >English</a></li><li><a id="zh-cn" href="/zh-cn/contributing.html" style="color: #22ab28">中文</a></li></ul>
        </li>
      
      <li><iframe src="https://ghbtns.com/github-btn.html?user=eggjs&repo=egg&type=star&count=true" frameborder="0" scrolling="0" width="150px" height="20px"></iframe></li>
    </ul>
    <a id="mobileTrigger" href="#" class="mobile-trigger">
      <ul>
        <li></li>
        <li></li>
        <li></li>
      </ul>
    </a>
  </header>
</div>
  <div id="container" class="container">
    <div class="page-main">
  <article class="markdown-body">
    <h1>代码贡献规范</h1>
    <p>有任何疑问，欢迎提交 <a href="https://github.com/eggjs/egg/issues" target="_blank" rel="noopener">issue</a>，
或者直接修改提交 <a href="https://github.com/eggjs/egg/pulls" target="_blank" rel="noopener">PR</a>!</p>
<h2 id="提交-issue"><a class="markdown-anchor" href="#提交-issue">#</a> 提交 issue</h2>
<ul>
<li>请确定 issue 的类型。</li>
<li>请避免提交重复的 issue，在提交之前搜索现有的 issue。</li>
<li>在标签(分类参考<strong>标签分类</strong>), 标题 或者内容中体现明确的意图。</li>
</ul>
<p>随后 egg 负责人会确认 issue 意图，更新合适的标签，关联 milestone，指派开发者。</p>
<p>标签可分为两类，type 和 scope</p>
<ul>
<li>type: issue 的类型，如 <code>feature</code>, <code>bug</code>, <code>documentation</code>, <code>performance</code>, <code>support</code> ...</li>
<li>scope: 修改文件的范围，如 <code>core: xx</code>，<code>plugin: xx</code>，<code>deps: xx</code></li>
</ul>
<h3 id="常用标签说明"><a class="markdown-anchor" href="#常用标签说明">#</a> 常用标签说明</h3>
<ul>
<li><code>support</code>: issue 提出的问题需要开发者协作排查，咨询，调试等等日常技术支持。</li>
<li><code>bug</code>: 一旦发现可能是 bug 的问题，请打上 <code>bug</code>，然后等待确认，一旦确认是 bug，此 issue 会被再打上 <code>confirmed</code>。
<ul>
<li>此时 issue 会被非常高的优先级进行处理。</li>
<li>如果此 bug 是正在影响线上应用正常运行，会再打上 <code>critical</code>，代表是最高优先级，需要马上立刻处理！</li>
<li>bug 会在最低需要修复的版本进行修复，如是在 <code>0.9.x</code> 要修复的，而当前最新版本是 <code>1.1.x</code>，
那么此 issue 还会被打上 <code>0.9</code>，<code>0.10</code>，<code>1.0</code>，<code>1.1</code>，代表需要修复到这些版本。</li>
</ul>
</li>
<li><code>core: xx</code>: 代表 issue 跟 core 内核相关，如 <code>core: antx</code> 代表跟 <code>antx</code> 配置相关。</li>
<li><code>plugin: xx</code>: 代表 issue 跟插件相关，如 <code>deps: session</code> 代表跟 <code>session</code> 插件相关。</li>
<li><code>deps: xx</code>: 代表 issue 跟 <code>dependencies</code> 模块相关，如 <code>deps: egg-cors</code> 代表跟 <code>egg-cors</code> 模块相关。</li>
<li><code>chore: documentation</code>: 代表发现了文档相关问题，需要修复文档说明。</li>
<li><code>cbd</code>: 代表跟服务器部署相关</li>
</ul>
<h2 id="编写文档"><a class="markdown-anchor" href="#编写文档">#</a> 编写文档</h2>
<p>所有功能点必须提交配套文档，文档须满足以下要求</p>
<ul>
<li>必须说清楚问题的几个方面：what（是什么），why（为什么），how（怎么做），可根据问题的特性有所侧重。</li>
<li>how 部分必须包含详尽完整的操作步骤，必要时附上 <strong>足够简单，可运行</strong> 的范例代码，
所有范例代码放在 <a href="https://github.com/eggjs/examples" target="_blank" rel="noopener">eggjs/examples</a> 库中。</li>
<li>提供必要的链接，如申请流程，术语解释和参考文档等。</li>
<li>同步修改中英文文档，或者在 PR 里面说明。</li>
</ul>
<h2 id="提交代码"><a class="markdown-anchor" href="#提交代码">#</a> 提交代码</h2>
<h3 id="提交-pull-request"><a class="markdown-anchor" href="#提交-pull-request">#</a> 提交 Pull Request</h3>
<p>如果你有仓库的开发者权限，而且希望贡献代码，那么你可以创建分支修改代码提交 PR，egg 开发团队会 review 代码合并到主干。</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 先创建开发分支开发，分支名应该有含义，避免使用 update、tmp 之类的</span></span><br><span class="line">$ git checkout -b branch-name</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开发完成后跑下测试是否通过，必要时需要新增或修改测试用例</span></span><br><span class="line">$ npm <span class="built_in">test</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 测试通过后，提交代码，message 见下面的规范</span></span><br><span class="line"></span><br><span class="line">$ git add . <span class="comment"># git add -u 删除文件</span></span><br><span class="line">$ git commit -m <span class="string">"fix(role): role.use must xxx"</span></span><br><span class="line">$ git push origin branch-name</span><br></pre></td></tr></table></figure>
<p>提交后就可以在 <a href="https://github.com/eggjs/egg/pulls" target="_blank" rel="noopener">egg</a> 创建 Pull Request 了。</p>
<p>由于谁也无法保证过了多久之后还记得多少，为了后期回溯历史的方便，请在提交 MR 时确保提供了以下信息。</p>
<ol>
<li>需求点（一般关联 issue 或者注释都算）</li>
<li>升级原因（不同于 issue，可以简要描述下为什么要处理）</li>
<li>框架测试点（可以关联到测试文件，不用详细描述，关键点即可）</li>
<li>关注点（针对用户而言，可以没有，一般是不兼容更新等，需要额外提示）</li>
</ol>
<h3 id="代码风格"><a class="markdown-anchor" href="#代码风格">#</a> 代码风格</h3>
<p>你的代码风格必须通过 eslint，你可以运行 <code>$ npm run lint</code> 本地测试。</p>
<h3 id="commit-提交规范"><a class="markdown-anchor" href="#commit-提交规范">#</a> Commit 提交规范</h3>
<p>根据 <a href="https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format" target="_blank" rel="noopener">angular 规范</a>提交 commit，
这样 history 看起来更加清晰，还可以自动生成 changelog。</p>
<figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">type</span>&gt;</span>(<span class="tag">&lt;<span class="name">scope</span>&gt;</span>): <span class="tag">&lt;<span class="name">subject</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">BLANK</span> <span class="attr">LINE</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">BLANK</span> <span class="attr">LINE</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">footer</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>（1）type</p>
<p>提交 commit 的类型，包括以下几种</p>
<ul>
<li>feat: 新功能</li>
<li>fix: 修复问题</li>
<li>docs: 修改文档</li>
<li>style: 修改代码格式，不影响代码逻辑</li>
<li>refactor: 重构代码，理论上不影响现有功能</li>
<li>perf: 提升性能</li>
<li>test: 增加修改测试用例</li>
<li>chore: 修改工具相关（包括但不限于文档、代码生成等）</li>
<li>deps: 升级依赖</li>
</ul>
<p>（2）scope</p>
<p>修改文件的范围（包括但不限于 doc, middleware, core, config, plugin）</p>
<p>（3）subject</p>
<p>用一句话清楚的描述这次提交做了什么</p>
<p>（4）body</p>
<p>补充 subject，适当增加原因、目的等相关因素，也可不写。</p>
<p>（5）footer</p>
<ul>
<li><strong>当有非兼容修改(Breaking Change)时必须在这里描述清楚</strong></li>
<li>关联相关 issue，如 <code>Closes #1, Closes #2, #3</code></li>
<li>如果功能点有新增或修改的，还需要关联文档 <code>doc</code> 和 <code>egg-init</code> 的 PR，如 <code>eggjs/egg-bin#123</code></li>
</ul>
<p>示例</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">fix($compile): [BREAKING_CHANGE] couple of unit tests for IE9</span><br><span class="line"></span><br><span class="line">Older IEs serialize html uppercased, but IE9 does not...</span><br><span class="line">Would be better to expect case insensitive, unfortunately jasmine does</span><br><span class="line">not allow to user regexps for throw expectations.</span><br><span class="line"></span><br><span class="line">Document change on eggjs/egg#123</span><br><span class="line"></span><br><span class="line">Closes #392</span><br><span class="line"></span><br><span class="line">BREAKING CHANGE:</span><br><span class="line"></span><br><span class="line">  Breaks foo.bar api, foo.baz should be used instead</span><br></pre></td></tr></table></figure>
<p>查看具体<a href="https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit" target="_blank" rel="noopener">文档</a></p>
<h2 id="发布管理"><a class="markdown-anchor" href="#发布管理">#</a> 发布管理</h2>
<p>egg 基于 <a href="http://semver.org/lang/zh-CN/" target="_blank" rel="noopener">semver</a> 语义化版本号进行发布。</p>
<h3 id="分支策略"><a class="markdown-anchor" href="#分支策略">#</a> 分支策略</h3>
<p><code>master</code> 分支为当前稳定发布的版本，<code>next</code> 分支为下一个开发中的大版本。</p>
<ul>
<li>只维护两个版本，除非有安全问题，否则修复只会 patch 到 <code>master</code> 和 <code>next</code> 分支，其他更新推动上层框架升级到稳定大版本的最新版本。</li>
<li>所有 API 的废弃都需要在当前的稳定版本上 <code>deprecate</code> 提示，并保证在当前的稳定版本上一直兼容到新版本的发布。</li>
<li><code>master</code> 分支不设置 publish tag，上层框架基于 semver 依赖稳定版本。</li>
<li><code>next</code> 分支设置 tag 为 <code>next</code>，上层框架可以通过 <code>egg@next</code> 引用开发中的版本进行测试。</li>
<li>egg 持续维护的版本以 Milestone 为准，只要是开着的版本都会进行修复。</li>
</ul>
<h3 id="发布策略"><a class="markdown-anchor" href="#发布策略">#</a> 发布策略</h3>
<p>每个大版本都有一个发布经理管理（PM），他/她要做的事情</p>
<h4 id="准备工作"><a class="markdown-anchor" href="#准备工作">#</a> 准备工作：</h4>
<ul>
<li>建立 milestone，确认需求关联 milestone，指派和更新 issues，如 <a href="https://github.com/eggjs/egg/milestone/1" target="_blank" rel="noopener">1.x milestone</a>。</li>
<li>从 <code>master</code> 分支新建 <code>next</code> 分支，并设置 tag 为 <code>next</code>。</li>
</ul>
<h4 id="发布前"><a class="markdown-anchor" href="#发布前">#</a> 发布前：</h4>
<ul>
<li>
<p>确认当前 Milestone 所有的 issue 都已关闭或可延期，完成性能测试。</p>
</li>
<li>
<p>发起一个新的 <a href="https://github.com/nodejs/node/pull/4181" target="_blank" rel="noopener">Release Proposal MR</a>，按照 <a href="https://github.com/nodejs/node/blob/master/CHANGELOG.md" target="_blank" rel="noopener">node CHANGELOG</a> 进行 <code>History</code> 的编写，修正文档中与版本相关的内容，commits 可以自动生成。</p>
  <figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ npm run commits</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>指定下一个大版本的 PM。</p>
</li>
</ul>
<h4 id="发布时"><a class="markdown-anchor" href="#发布时">#</a> 发布时：</h4>
<ul>
<li>将老的稳定版本（master）备份到以当前大版本为名字的分支上（例如 <code>1.x</code>），并设置 tag 为 <code>release-{v}.x</code>（ v 为当前版本，例如 <code>release-1.x</code>）。</li>
<li>将 <code>next</code> 分支推送到 <code>master</code>，成为新的稳定版本分支，并去除 <code>next</code> tag，修改 README 中与分支相关的内容。</li>
<li>发布新的稳定版本到 <a href="http://npmjs.com/" target="_blank" rel="noopener">npm</a>，并通知上层框架进行更新。</li>
<li><code>npm publish</code> 之前，请先阅读<a href="https://fengmk2.com/blog/2016/how-i-publish-a-npm-package" target="_blank" rel="noopener">『我是如何发布一个 npm 包的』</a>。</li>
</ul>
<p>上述描述中所有的设置 tag 都是指在 <code>package.json</code> 中设置 npm 的 tag。</p>
<figure class="highlight"><table><tr><td class="code"><pre><span class="line">"publishConfig": &#123;</span><br><span class="line">  "tag": "next"</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  </article>
  <aside id="mobileAside" class="toc">
  <div class="mobile-menu">
    <ul>
      <li><a href="/zh-cn/intro/" alt="指南">指南</a></li><li><a href="/api/" alt="API">API</a></li><li><a href="/zh-cn/tutorials/index.html" alt="教程">教程</a></li><li><a href="https://github.com/search?q=topic%3Aegg-plugin&type=Repositories" alt="插件">插件</a></li><li><a href="https://github.com/eggjs/egg/releases" alt="发布日志">发布日志</a></li>
      
      
        <li class="translations">
          <a class="nav-link">Translations</a>
          <span class="arrow"></span><ul id="dropdownContent" class="dropdown-content"><li><a id="en" href="/en/contributing.html" >English</a></li><li><a id="zh-cn" href="/zh-cn/contributing.html" style="color: #22ab28">中文</a></li></ul>
        </li>
      
    </ul>
  </div>
  <dl><dt id="title-Intro" style="cursor: pointer;" class="aside-title">新手指南<a id="collapse-icon-Intro" class="icon opend"></a></dt><dd id=panel-Intro><ul><li><a href="/zh-cn/intro/index.html" class="menu-link">Egg.js 是什么?</a></li><li><a href="/zh-cn/intro/egg-and-koa.html" class="menu-link">Egg.js 和 Koa</a></li><li><a href="/zh-cn/intro/quickstart.html" class="menu-link">快速入门</a></li><li><a href="/zh-cn/tutorials/progressive.html" class="menu-link">渐进式开发</a></li><li><a href="/zh-cn/migration.html" class="menu-link">2.x 升级指南</a></li></ul></dd><dt id="title-Basics" style="cursor: pointer;" class="aside-title">基础功能<a id="collapse-icon-Basics" class="icon opend"></a></dt><dd id=panel-Basics><ul><li><a href="/zh-cn/basics/structure.html" class="menu-link">目录结构</a></li><li><a href="/zh-cn/basics/objects.html" class="menu-link">内置对象</a></li><li><a href="/zh-cn/basics/env.html" class="menu-link">运行环境</a></li><li><a href="/zh-cn/basics/config.html" class="menu-link">配置</a></li><li><a href="/zh-cn/basics/middleware.html" class="menu-link">中间件</a></li><li><a href="/zh-cn/basics/router.html" class="menu-link">Router</a></li><li><a href="/zh-cn/basics/controller.html" class="menu-link">Controller</a></li><li><a href="/zh-cn/basics/service.html" class="menu-link">Service</a></li><li><a href="/zh-cn/basics/plugin.html" class="menu-link">插件</a></li><li><a href="/zh-cn/basics/schedule.html" class="menu-link">定时任务</a></li><li><a href="/zh-cn/basics/extend.html" class="menu-link">框架扩展</a></li><li><a href="/zh-cn/basics/app-start.html" class="menu-link">启动自定义</a></li></ul></dd><dt id="title-Core" style="cursor: pointer;" class="aside-title">核心功能<a id="collapse-icon-Core" class="icon opend"></a></dt><dd id=panel-Core><ul><li><a href="/zh-cn/core/development.html" class="menu-link">本地开发</a></li><li><a href="/zh-cn/core/unittest.html" class="menu-link">单元测试</a></li><li><a href="/zh-cn/core/deployment.html" class="menu-link">应用部署</a></li><li><a href="/zh-cn/core/logger.html" class="menu-link">日志</a></li><li><a href="/zh-cn/core/httpclient.html" class="menu-link">HttpClient</a></li><li><a href="/zh-cn/core/cookie-and-session.html" class="menu-link">Cookie and Session</a></li><li><a href="/zh-cn/core/cluster-and-ipc.html" class="menu-link">多进程模型和进程间通讯</a></li><li><a href="/zh-cn/core/view.html" class="menu-link">模板渲染</a></li><li><a href="/zh-cn/core/error-handling.html" class="menu-link">异常处理</a></li><li><a href="/zh-cn/core/security.html" class="menu-link">安全</a></li><li><a href="/zh-cn/core/i18n.html" class="menu-link">国际化</a></li></ul></dd><dt id="title-Tutorials" style="cursor: pointer;" class="aside-title">教程<a id="collapse-icon-Tutorials" class="icon opend"></a></dt><dd id=panel-Tutorials><ul><li><a href="/zh-cn/tutorials/mysql.html" class="menu-link">MySQL</a></li><li><a href="/zh-cn/tutorials/restful.html" class="menu-link">RESTful API</a></li><li><a href="/zh-cn/tutorials/passport.html" class="menu-link">Passport 鉴权</a></li><li><a href="/zh-cn/tutorials/socketio.html" class="menu-link">Socket.IO</a></li><li><a href="/zh-cn/tutorials/assets.html" class="menu-link">静态资源</a></li><li><a href="/zh-cn/tutorials/typescript.html" class="menu-link">TypeScript</a></li></ul></dd><dt id="title-Advanced" style="cursor: pointer;" class="aside-title">进阶<a id="collapse-icon-Advanced" class="icon opend"></a></dt><dd id=panel-Advanced><ul><li><a href="/zh-cn/advanced/loader.html" class="menu-link">Loader</a></li><li><a href="/zh-cn/advanced/plugin.html" class="menu-link">插件开发</a></li><li><a href="/zh-cn/advanced/framework.html" class="menu-link">框架开发</a></li><li><a href="/zh-cn/advanced/cluster-client.html" class="menu-link">多进程研发模式增强</a></li><li><a href="/zh-cn/advanced/view-plugin.html" class="menu-link">模板插件开发规范</a></li><li><a href="/zh-cn/style-guide.html" class="menu-link">代码风格指南</a></li></ul></dd><dt id="title-Community" style="cursor: pointer;" class="aside-title">社区<a id="collapse-icon-Community" class="icon opend"></a></dt><dd id=panel-Community><ul><li><a href="/zh-cn/plugins/" class="menu-link">内置插件列表</a></li><li><a href="/zh-cn/contributing.html" class="menu-link">如何贡献</a></li><li><a href="/zh-cn/resource.html" class="menu-link">资源</a></li><li><a href="/zh-cn/faq.html" class="menu-link">常见问题</a></li></ul></dd></dl>
</aside>
<script>
var mobileTrigger = document.getElementById('mobileTrigger');
var mobileAside = document.getElementById('mobileAside');

var expandMenu = function(title) {
  // handle icon
  const collapseIcon = document.getElementById('collapse-icon-' + title);
  if (collapseIcon) {
    collapseIcon.className = 'icon opend';
  }
  // handle panelEle
  const panelEle = document.getElementById('panel-' + title);
  if (panelEle) {
    panelEle.className = '';
  }
}

var collapseMenu = function(title) {
  // handle icon
  const collapseIcon = document.getElementById('collapse-icon-' + title);
  if (collapseIcon) {
    collapseIcon.className = 'icon closed';
  }
  // handle panelEle
  const panelEle = document.getElementById('panel-' + title);
  if (panelEle) {
    panelEle.className = 'aside-panel-hidden';
  }
}

mobileAside.onclick = function(e) {
  const targetId = e.target.id;
  if (targetId && (targetId.indexOf('title-') > -1 || targetId.indexOf('collapse-icon-') > -1)) {
    const title = targetId.replace('title-', '').replace('collapse-icon-', '');
    try { 
      // the the browser may have no localStroage or JSON.parse may throw exception.
      const menuInfo = JSON.parse(window.localStorage.getItem('menuInfo'));
        
      // current menu status
      const curClosed = menuInfo[title] ? menuInfo[title].closed : false; // default false

      // change UI
      curClosed ? expandMenu(title) : collapseMenu(title);

      // save menuInfo to localStorage
      menuInfo[title] = { closed: !curClosed } // opposite
      window.localStorage.setItem('menuInfo', JSON.stringify(menuInfo));
    } catch (e) {}
  }
};

mobileTrigger.onclick = function(e) {
  e.preventDefault();
  if (mobileAside.className.indexOf('mobile-show') === -1) {
    mobileAside.className += ' mobile-show';
  } else {
    mobileAside.className = 'toc';
  }
};

(function() {
  // save data to localStorage because the page will refresh when user change the url.
  let menuInfo;
  try { 
    // the the browser may have no localStroage or JSON.parse may throw exception.
    menuInfo = JSON.parse(window.localStorage.getItem('menuInfo'));
    if (!menuInfo) {
      menuInfo = {};
      window.localStorage.setItem('menuInfo', JSON.stringify(menuInfo));
    }
  } catch (e) {
    menuInfo = {}; // default {}
  }

  for (const title in menuInfo) {
    if (menuInfo[title] && menuInfo[title].closed) { // menu in closed status.
      collapseMenu(title);
    } else {
      expandMenu(title);
    }
  }

  // highlight menu
  const pathname = window.location.pathname;
  const selector = `a[href="${pathname}"].menu-link,a[href="${pathname}index.html"].menu-link`;
  const menuItem = mobileAside.querySelector(selector);
  if (menuItem) { menuItem.className += ' highlight'; }
})();
</script>

</div>

  </div>
</body>
<script src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script>
<script>
docsearch({
  apiKey: '1561de31a86f79507ea00cdb54ce647c',
  indexName: 'eggjs',
  inputSelector: '#search-query',
});
</script>
<div class="cnzz">
<script src="https://s11.cnzz.com/z_stat.php?id=1261142226&web_id=1261142226" language="JavaScript"></script>
</div>

</html>
